/**
 * Storage 变更事件的详细信息
 */
export interface StorageChangeEvent extends Event {
  key: string;
  newValue: string;
  oldValue: string | null;
  storageArea: 'local' | 'session';
}

type StorageType = 'local' | 'session';
type StorageInstance = typeof localStorage | typeof sessionStorage;

/**
 * Storage 监听器配置选项
 */
export interface StorageMonitorOptions {
  /** 监听类型：'local' | 'session' | 'both' */
  type?: 'local' | 'session' | 'both';
  /** 是否在值相同时也触发事件 */
  emitUnchanged?: boolean;
  /** 自定义错误处理函数 */
  onError?: (error: Error) => void;
}

/**
 * 监控浏览器存储变化
 * @description 监听并增强 localStorage 和 sessionStorage 的变更事件
 * @param options - 监听器配置选项
 * @returns 清理函数
 * @example
 * const cleanup = monitorStorage({ type: 'both' });
 * window.addEventListener('local', e => console.log(e));
 * window.addEventListener('session', e => console.log(e));
 * cleanup();
 */
export const monitorStorage = (options: StorageMonitorOptions = {}) => {
  const {
    type = 'both',
    emitUnchanged = false,
    onError = console.error
  } = options;

  const enhanceStorage = (storage: StorageInstance, type: StorageType) => {
    const original = {
      setItem: storage.setItem.bind(storage),
      removeItem: storage.removeItem.bind(storage),
      clear: storage.clear.bind(storage)
    };

    const createEvent = (key: string, newValue: string, oldValue: string | null = null) => {
      const event = new Event(type) as StorageChangeEvent;
      event.key = key;
      event.newValue = newValue;
      event.oldValue = oldValue;
      event.storageArea = type;
      return event;
    };

    const dispatchStorageEvent = (event: StorageChangeEvent) => {
      try {
        window.dispatchEvent(event);
      } catch (error) {
        onError(error as Error);
      }
    };

    // 增强 setItem
    storage.setItem = (key: string, value: string) => {
      const oldValue = storage.getItem(key);
      if (!emitUnchanged && oldValue === value) {
        return original.setItem(key, value);
      }
      original.setItem(key, value);
      dispatchStorageEvent(createEvent(key, value, oldValue));
    };

    // 增强 removeItem
    storage.removeItem = (key: string) => {
      const oldValue = storage.getItem(key);
      original.removeItem(key);
      dispatchStorageEvent(createEvent(key, '', oldValue));
    };

    // 增强 clear
    storage.clear = () => {
      original.clear();
      dispatchStorageEvent(createEvent('', ''));
    };

    return original;
  };

  const enhanced = {
    local: type === 'local' || type === 'both' 
      ? enhanceStorage(localStorage, 'local')
      : null,
    session: type === 'session' || type === 'both'
      ? enhanceStorage(sessionStorage, 'session')
      : null
  };

  // 返回清理函数
  return () => {
    if (enhanced.local) {
      Object.assign(localStorage, enhanced.local);
    }
    if (enhanced.session) {
      Object.assign(sessionStorage, enhanced.session);
    }
  };
};